from rest_framework import serializers

from django.contrib.auth.password_validation import validate_password
from django.db.models import Q

from .models import MyUser

from projects.models import ClinicalProjects

import re


class MyUserListSerializer(serializers.ModelSerializer):

    class Meta:
        model = MyUser
        fields = ('url', 'id', 'email', 'phone')


class AreaOnlySerializer(serializers.Serializer):
    prj_code = serializers.CharField(required=True,
                                     help_text='项目代号',
                                     write_only=True)

    def validate_prj_code(self, value):
        try:
            cli_obj = ClinicalProjects.objects.get(prj_code=value)
        except ClinicalProjects.DoesNotExist:
            raise serializers.ValidationError('项目代号错误')

        if not cli_obj:
            raise serializers.ValidationError('查询数据错误')
        return value


class AreaListSerializer(serializers.ModelSerializer):
    prj_code = serializers.CharField(required=True,
                                     help_text='项目代号',
                                     write_only=True)

    class Meta:
        model = MyUser
        fields = ('area', 'prj_code')
        extra_kwargs = {
            'area': {
                'required': True
            }
        }

    def validate_prj_code(self, value):
        try:
            cli_obj = ClinicalProjects.objects.get(prj_code=value)
        except ClinicalProjects.DoesNotExist:
            raise serializers.ValidationError('项目代号错误')

        if not cli_obj:
            raise serializers.ValidationError('查询数据错误')
        return value


class HospitalListSerializer(serializers.ModelSerializer):
    prj_code = serializers.CharField(required=True,
                                     help_text='项目代号',
                                     write_only=True)

    class Meta:
        model = MyUser
        fields = ('hospital', 'prj_code')
        extra_kwargs = {
            'hospital': {
                'required': True
            }
        }

    def validate_prj_code(self, value):
        try:
            cli_obj = ClinicalProjects.objects.get(prj_code=value)
        except ClinicalProjects.DoesNotExist:
            raise serializers.ValidationError('项目代号错误')

        if not cli_obj:
            raise serializers.ValidationError('查询数据错误')
        return value


class ProjectsSerializer(serializers.ModelSerializer):

    class Meta:
        model = ClinicalProjects
        fields = ('name', 'status', 'linkurl', 'description')


class MyUserDetailSerializer(serializers.ModelSerializer):
    # myprojects = ProjectsSerializer(many=True, read_only=True)
    myprojects = serializers.SerializerMethodField()

    class Meta:
        model = MyUser
        fields = ('url', 'id', 'email', 'phone', 'user_name', 'sex',
                  'area', 'hospital', 'address', 'myprojects')

    def get_myprojects(self, obj):
        g_p = ['/{}/'.format(i.split('.')[0]) for i in obj.get_group_permissions()]
        all_projects = ClinicalProjects.objects.filter(linkurl__in=g_p).order_by('linkurl')
        bb = ProjectsSerializer(data=all_projects, many=True)
        bb.is_valid()
        return bb.data

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            if attr == 'password':
                instance.set_password(value)
            else:
                setattr(instance, attr, value)
        instance.save()
        return instance


class ChangePasswordSerializer(serializers.Serializer):
    """
    Serializer for password change endpoint.
    """
    old_password = serializers.CharField(help_text=u'旧密码', required=True)
    new_password = serializers.CharField(help_text=u'新密码', required=True)

    def validate_new_password(self, value):
        validate_password(value)
        return value


class CreateUserSerializer(serializers.ModelSerializer):
    """
    创建用户的序列化器
    """
    password2 = serializers.CharField(label="确认密码",
                                      write_only=True,
                                      help_text="验证密码")

    class Meta:
        model = MyUser

        fields = ("email", "password", "password2", "phone", "user_name")

        # write_only_fields = ("phone", "user_name")

        extra_kwargs = {
            "password": {
                "write_only": True,
                "min_length": 6,
                "max_length": 20,
                "help_text": "密码",
                "error_messages": {
                    "min_length": "密码允许6-20个字符",
                    "max_length": "密码允许6-20个字符"
                }
            },
            "phone": {
                "write_only": True,
            },
            "user_name": {
                "write_only": True,
                "required": True
            },
        }

    def validate(self, data):
        """
        验证参数
        :param data:
        :return:
        """
        value = data["phone"]
        email = data["email"]

        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式错误')

        from django.db.models import Q
        try:
            user = MyUser.objects.get(Q(phone=value) | Q(email=email))
        except MyUser.DoesNotExist:
            if data["password"] != data["password2"]:
                raise serializers.ValidationError("两次密码输入不一致")
        else:
            if user:
                return serializers.ValidationError("用户已存在")
        return data

    def create(self, validated_data):
        """
        创建用户
        :param validated_data:
        :return:
        """
        del validated_data["password2"]

        user = super().create(validated_data)

        user.set_password(validated_data['password'])

        user.save()

        return user


class EmailSerializer(serializers.Serializer):
    email = serializers.CharField(help_text='用户邮箱', required=True)

    def validate(self, data):
        email = data['email']

        try:
            user = MyUser.objects.filter(email=email)
        except Exception as e:
            raise serializers.ValidationError(e)

        if not user:
            raise serializers.ValidationError('用户不存在, 请先注册')

        return data


class LoginSerializer(serializers.Serializer):
    url = serializers.HyperlinkedRelatedField(help_text='url',
                                              read_only=True,
                                              view_name='myuser-detail')
    id = serializers.IntegerField(help_text='ID', read_only=True)

    email = serializers.CharField(help_text='用户邮箱/手机号',
                                  required=True,
                                  write_only=True)

    password = serializers.CharField(help_text='密码',
                                     required=True,
                                     write_only=True)

    def validate(self, data):
        email = data['email']
        password = data['password']

        try:
            user = MyUser.objects.get(Q(email=email) | Q(phone=email))
        except MyUser.DoesNotExist:
            raise serializers.ValidationError('用户信息错误')

        if not user:
            raise serializers.ValidationError('用户不存在, 请先注册')

        is_correct = user.check_password(password)
        if not is_correct:
            raise serializers.ValidationError('密码输入有误, 请查看账户或密码')

        data['id'] = user.id
        data['url'] = user
        return data
